﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CID.Execution.Support.Information;
using CID.Execution.Support.PackageHandling;
using CID.Execution.Support.Scripting;
using CID.Execution.Support.TemplateHandling;

namespace CID.Execution.Agent
{
    class DeploymentScriptExecuter : BaseScriptExecuter<LocationDeploymentScript, DeploymentScriptStep>
    {
        public DeploymentScriptExecuter(LocationDeploymentScript script) : base(script) { }

        protected override void ExecuteStep(DeploymentScriptStep step, StringBuilder detailsBuilder)
        {
            AppendMessage(detailsBuilder, "Started deployment of Component: {0}, Version: {1}, Package: {2}", step.Version.Component.Name, step.Version.Name, step.Package.Comment);

            var packageHandler = PackageHandlerFactory.Instance.CreatePackageHandler(step.Package.Type);
            var packageHandlingToken = packageHandler.PrepareForUsage(step.Package);
            try
            {

                var templateHandler = TemplateHandlerFactory.Instance.CreateTemplateHandler(step.Template.Type);
                templateHandler.ExecuteTemplate(step.Template, step.ParameterValues,
                    GetGeneralAdditionalParameterValues().Concat(GetSpecificAdditionalParameterValues(step)).Concat(packageHandlingToken.GetPackageRelatedParameterValues()), step.TargetServers, detailsBuilder);
            }
            finally
            {
                packageHandler.Release(packageHandlingToken);
            }

            AppendMessage(detailsBuilder, "Ended deployment of Component: {0}, Version: {1}, Package: {2}", step.Version.Component.Name, step.Version.Name, step.Package.Comment);
        }

        private IEnumerable<ParameterValueInfo> GetSpecificAdditionalParameterValues(DeploymentScriptStep step)
        {
            var result = new List<ParameterValueInfo>();
            result.Add(ParameterValueInfo.CreateAdditionalParameterValue(ParameterValueInfo.ReservedParameterNames.ComponentName, step.Version.Component.Name));
            result.Add(ParameterValueInfo.CreateAdditionalParameterValue(ParameterValueInfo.ReservedParameterNames.VersionName, step.Version.Name));
            result.Add(ParameterValueInfo.CreateAdditionalParameterValue(ParameterValueInfo.ReservedParameterNames.PackageComment, step.Package.Comment));
            return result;
        }

        protected override void OnExecutionStarted(LocationDeploymentScript script, StringBuilder detailsBuilder)
        {
            AppendMessage(detailsBuilder, "Started Deployment");
        }

        protected override void OnExecutionEnded(LocationDeploymentScript script, string details, bool error)
        {
            var controllerProxy = ControllerServiceProxyFactory.Create();
            try
            {
                controllerProxy.NotifyDeploymentCompleted(script.DeploymentUniqueIdentifier, script.LocationId, details, error);
            }
            catch (Exception ex)
            {
                NotifyControllerCommnunicationError(ex);
            }
            finally
            {
                ControllerServiceProxyFactory.Dispose(controllerProxy);
            }
        }
    }
}
